<template>
  <div :class="$style.wrap">
    <Button type="primary" @click="openExportPane">
      <slot></slot>
    </Button>
    <el-dialog title="导出" :visible.sync="visible" :close-on-click-modal="false" @open="handlerOpen" @close="resetForm">
      <el-alert :class="$style.alert" title="请合理选择查询条件，每次最多导出5万条数据" type="warning" :closable="false">
      </el-alert>
      <FormContainer :column="1">
        <el-form ref="form" :model="formData" :rules="formRules" label-width="90px">
          <el-form-item label="导出类型" prop="type">
            <el-radio-group v-model="formData.type">
              <el-radio :label="1">导出数据</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="导出范围" prop="range">
            <el-radio-group v-model="formData.range">
              <el-radio :label="1" :disabled="!hasDataSource">选中的数据行</el-radio>
              <el-radio :label="2">符合当前查询条件的全部数据行</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item prop="filename" label="请输入文件名">
            <el-input v-model="formData.filename" placeholder="请输入文件名"></el-input>
          </el-form-item>
          <el-form-item>
            <Button @click="canacelHandle">取消</Button>
            <Button type="primary" @click="confirmHandle">确定</Button>
          </el-form-item>
        </el-form>
      </FormContainer>
    </el-dialog>
  </div>
</template>
<script>
import FormContainer from '@/components/FormContainer'
import { exportExcelFile } from '@/utils/dataToExcel'
import { downFileByStream, parseTime } from '@/utils'
export default {
  name: 'ExportPane',
  components: {
    FormContainer
  },
  props: {
    tableConfig: { // table-box 组件配置
      type: Object,
      default: undefined
    },
    dataSource: { // 导出数据源
      type: Array,
      default: () => ([])
    },
    dataSourceFunc: { // 获取数据源函数
      type: Function,
      default: undefined
    },
    queryDataFun: { // 查询参数生成函数
      type: Function,
      default: undefined
    },
    extension: { // 扩展名
      type: String,
      default: '.xlsx'
    },
    exclude: { // 排除选项
      type: Array,
      default: () => []
    },
    fields: { // 导出字段
      type: Object,
      default: () => ({})
    },
    method: { // 请求方式
      type: String,
      default: 'POST'
    },
    url: { // 地址
      type: String,
      default: ''
    },
    sepCol: { // 列分隔符
      type: String,
      default: '/c$/o$/l'
    },
    sepRow: { // 行分隔符
      type: String,
      default: '/r!@$#/n'
    },
    filename: { // 文件名
      type: String,
      default: ''
    },
    exportFile: { // 后台返回的文件流
      type: Function,
      default: undefined
    },
    otherRaw: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      visible: false,
      formData: {
        type: 1,
        range: 2,
        filename: ''
      },
      formRules: {
        type: [],
        range: [],
        filename: [
          { required: true, message: '请输入文件名', trigger: 'change' }
        ]
      }
    }
  },
  computed: {
    hasDataSource() {
      return this.dataSource.length > 0
    }
  },
  created() {
  },
  methods: {
    handlerOpen() {
      if (this.filename) {
        this.$set(this.formData, 'filename', `${this.filename}_${parseTime(new Date(), '{y}-{m}-{d}_{h}_{i}_{s}')}`)
      }
    },
    openExportPane() {
      if (this.hasDataSource) {
        this.$set(this.formData, 'range', 1)
      } else {
        this.$set(this.formData, 'range', 2)
      }
      this.visible = true
    },
    confirmHandle() {
      return this.$refs.form.validate().then(async() => {
        const data = {
          filename: `${this.formData.filename}.${('' || this.extension).replace('.', '')}`,
          method: this.method,
          fields: this.fields,
          tableConfig: this.tableConfig,
          exclude: this.exclude,
          sepCol: this.sepCol,
          sepRow: this.sepRow
        }
        if (this.formData.range === 1) {
          data.dataSource = this.dataSource
          return exportExcelFile(data).then(() => {
            this.visible = false
          }).catch(() => {
            this.$message.error('导出失败！')
            this.visible = false
          })
        }

        // 当后台返回的是文件流时
        if (this.exportFile instanceof Function) {
          return this.getExportFile().then(() => {
            this.visible = false
          }).catch(() => {
            this.$message.error('导出失败！')
            this.visible = false
          })
        }

        // 前端分页导出
        if (this.dataSourceFunc instanceof Function) {
          const result = this.dataSourceFunc()
          if (result instanceof Promise) {
            return result.then(resData => {
              data.dataSource = resData
              return exportExcelFile(data).then(() => {
                this.visible = false
              })
            }).catch(() => {
              this.$message.error('导出失败！')
              this.visible = false
            })
          } else {
            data.dataSource = result
            return exportExcelFile(data).then(() => {
              this.visible = false
            }).catch(() => {
              this.$message.error('导出失败！')
              this.visible = false
            })
          }
        }

        const qp = this.queryDataFun('export')
        if (qp instanceof Promise) {
          await qp.then(res => {
            data.bodyData = {
              filtersRaw: res
            }
          }).catch(async() => {
            await this.$msgbox({
              title: '提示',
              type: 'warning',
              message: '请先选择导出条件'
            }).then(() => {
              this.visible = false
              return Promise.reject()
            })
          })
        } else {
          data.bodyData = {
            filtersRaw: qp
          }
        }
        // 额外参数
        data.bodyData.paramsRaw = this.otherRaw
        if (this.tableConfig.sort) {
          data.bodyData.sort = this.tableConfig.sort
        }
        data.method = this.method
        data.url = this.url
        return exportExcelFile(data).then(res => {
          this.visible = false
        }).catch(() => {
          this.$message.error('导出失败！')
          this.visible = false
        })
      })
    },
    resetForm() {
      this.$refs.form.resetFields()
    },
    canacelHandle() {
      this.resetForm()
      this.visible = false
    },
    // 如果后台返回的是文件
    getExportFile() {
      return this.exportFile().then(res => {
        let filename = this.formData.filename
        if (res.config.responseType !== 'blob') {
          filename = filename + this.extension
        }
        downFileByStream(res.data, filename)
      })
    }
  }
}
</script>
<style lang='scss' module>
.wrap{
  display: inline-block;
  text-align: left !important;
}
.alert{
  line-height: initial;
  font-size: initial;
  margin-top: -10px;
  margin-bottom: 5px;
}
</style>
